#ifndef QCLOG_HPP
#define QCLOG_HPP

#include "qcregistry.h"
#include <QDebug>

#define QCLOG_SET_CONSOLE_LEVEL(level)          QcLog::set_console_level(level);
#define QCLOG_SET_CONSOLE_PATTERN(pattern)      QcLog::set_console_pattern(pattern);
#define QCLOG_SET_FILE_LEVEL(level)             QcLog::set_file_level(level);
#define QCLOG_SET_FILE_PATTERN(pattern)         QcLog::set_file_pattern(pattern);
#define QCLOG_SET_FILE_PATHNAME(pathname)       QcLog::set_file_pathname(pathname);
#define QCLOG_SET_FILE_ACTIVATION(is)           QcLog::set_file_activation(is);
#define QCLOG_SET_HIJACK_QDEBUG(is)             QcLog::set_hijack_qdebug(is);

#define QCLOG_INFO(message)                     QcLog::info(__FILE__, __LINE__, __FUNCTION__, message);
#define QCLOG_DEBUG(message)                    QcLog::debug(__FILE__, __LINE__, __FUNCTION__, message);
#define QCLOG_WARNING(message)                  QcLog::warning(__FILE__, __LINE__, __FUNCTION__, message);
#define QCLOG_CRITICAL(message)                 QcLog::critical(__FILE__, __LINE__, __FUNCTION__, message);
#define QCLOG_FATAL(message)                    QcLog::fatal(__FILE__, __LINE__, __FUNCTION__, message);

namespace QcLog {

inline QcLog::QcLogger *default_logger_raw()
{
    return Details::QcRegistry::instance().get_default_raw();
}

template<typename T>
inline void info(const char* file, int line, const char* function, const T &msg)
{
    source_loc msg_loc(file, line, function);
    default_logger_raw()->info(msg_loc, msg);
}

template<typename T>
inline void debug(const char* file, int line, const char* function, const T &msg)
{
    source_loc msg_loc(file, line, function);
    default_logger_raw()->debug(msg_loc, msg);
}

template<typename T>
inline void warning(const char* file, int line, const char* function, const T &msg)
{
    source_loc msg_loc(file, line, function);
    default_logger_raw()->warning(msg_loc, msg);
}

template<typename T>
inline void critical(const char* file, int line, const char* function, const T &msg)
{
    source_loc msg_loc(file, line, function);
    default_logger_raw()->critical(msg_loc, msg);
}

template<typename T>
inline void fatal(const char* file, int line, const char* function, const T &msg)
{
    source_loc msg_loc(file, line, function);
    default_logger_raw()->fatal(msg_loc, msg);
}

inline void set_console_level(Level log_level)
{
    default_logger_raw()->set_console_level(log_level);
}

inline void set_console_pattern(const QString &pattern)
{
    default_logger_raw()->set_console_pattern(pattern);
}

inline void set_file_level(Level file_level)
{
    default_logger_raw()->set_file_level(file_level);
}

inline void set_file_pattern(const QString &pattern)
{
    default_logger_raw()->set_file_pattern(pattern);
}

inline void set_file_pathname(const QString &pathname)
{
    default_logger_raw()->set_file_pathname(pathname);
}

inline void set_file_activation(const bool &activation)
{
    default_logger_raw()->set_file_activation(activation);
}

inline void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    switch (type)
    {
        case QtInfoMsg:
            info(context.file, context.line, context.category, msg);
            break;
        case QtDebugMsg:
            debug(context.file, context.line, context.category, msg);
            break;
        case QtWarningMsg:
            warning(context.file, context.line, context.category, msg);
            break;
        case QtCriticalMsg:
            critical(context.file, context.line, context.category, msg);
            break;
        case QtFatalMsg:
            fatal(context.file, context.line, context.category, msg);
            break;
    }
}

inline void set_hijack_qdebug(const bool &is)
{
    if(is)
    {
        qInstallMessageHandler(outputMessage);
    }
    else
    {
        qInstallMessageHandler(nullptr);
    }
}

} //namespace QcLog

#endif // QCLOG_HPP
